<?php
/**
 * Created by PhpStorm.
 * User: whwyy
 * Date: 2018/11/8 0008
 * Time: 18:18
 */

namespace BeReborn\Service\Common;

use BeReborn;
use BeReborn\Core\JSON;
use BeReborn\Error\Logger;
use BeReborn\Http\Request;
use BeReborn\Http\Response;
use BeReborn\Http\Context;
use Exception;
use Swoole\Error;
use Swoole\Coroutine;
use BeReborn\Service\Base\ServerBase;

/**
 * Class ServerRequest
 * @package BeReborn\Server
 */
class ServerRequest extends ServerBase
{
    const AFTER_REQUEST = 'AFTER_REQUEST';
    const RELEASE_ALL = 'RELEASE_ALL';

    /**
     * @param \Swoole\Http\Request $request
     * @param \Swoole\Http\Response $response
     * @return bool|string|void
     * @throws Exception
     */
    public function onRequest(\Swoole\Http\Request $request, \Swoole\Http\Response $response)
    {
//		register_shutdown_function([$this, 'onShutdown'], $response);
        Coroutine::defer(function () {
            fire(ServerRequest::AFTER_REQUEST);
            Logger::insert();
        });
        try {
            $sResponse = static::setContext($request, $response);
            $handler = BeReborn::getRouter()->runHandler();
            return $sResponse->send($handler, 200);
        } catch (Error | \Throwable $exception) {
            if (isset($sResponse)) {
                return $sResponse->send($this->format($exception), 200);
            }
            $this->onShutdown($response);
        }
    }


    /**
     * @param $response
     */
    public function onShutdown($response)
    {
        $error = error_get_last();
        $types = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR];
        if (in_array($error['type'], $types)) {
            $response->status(500);
            $response->end($error['message']);
        }
    }


    /**
     * @param Exception|Error $exception
     * @return false|int|mixed|string
     * @throws Exception
     */
    public function format($exception)
    {
        $errorInfo = [
            'message' => $exception->getMessage(),
            'file' => $exception->getFile(),
            'line' => $exception->getLine()
        ];
        $this->error(var_export($errorInfo, true));

        $code = $exception->getCode() == 0  ? 500 : $exception->getCode();

        $trance = array_slice($exception->getTrace(), 0, 10);
        Logger::write(print_r($trance, true), 'exception');

        return JSON::to($code, $errorInfo['message'], $errorInfo);
    }

    /**
     * @param $request
     * @param $response
     * @return Response
     * @throws Exception
     */
    public static function setContext($request, $response): Response
    {
        $request = Request::create($request);
        Context::setRequest($request);
        return Response::setResponse($response);
    }

}
